package com.wpos;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

/**
 * Created by bruce on 2016/5/22.
 */
public class WPosUtil {

    private static final String sign_type = "MD5";
    private static final String bp_id = "55dc1561fa0bab42b2c2b3d0";
    private static final String key = "L8hS2nhIlietf3el83z9wfjpQUVjHghd";
    private static final String notify_url = "http://apps.weipass.cn/cashier/openapi/orderinfo/query";

    private static final String charset = "UTF-8";

    public static String getPaymentInfo(String outTradeNo) throws NoSuchAlgorithmException,
            HttpException, IOException {

        Map<String, String> sigMap = new HashMap<String, String>();
        sigMap.put("bp_id", bp_id);
        sigMap.put("out_trade_no", outTradeNo);
        sigMap.put("input_charset", charset);
        String sign = getSign(sigMap);

        Map<String, String> paramsMap = new HashMap<String, String>();
        paramsMap.put("sign_type", sign_type);
        paramsMap.put("sign", sign);
        paramsMap.put("bp_id", bp_id);
        paramsMap.put("out_trade_no", outTradeNo);
        paramsMap.put("input_charset", charset);

        String params = WPosUtil.concatParams(paramsMap);
        String json = WPosUtil.post(notify_url, params);

        return json;
    }

    public static String getSign(Map<String, String> dataMap) throws NoSuchAlgorithmException, UnsupportedEncodingException {

        List<String> keyList = new ArrayList<String>(dataMap.keySet());
        Collections.sort(keyList);
        StringBuilder builder = new StringBuilder();
        for (String mapKey : keyList) {
            builder.append(mapKey).append("=").append(dataMap.get(mapKey))
                    .append("&");
        }
        builder.append("key=").append(key);
        MessageDigest md5 = MessageDigest.getInstance(sign_type);
        md5.update(builder.toString().getBytes(charset));
        byte[] md5Bytes = md5.digest();
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }

    public static String post(String url, String data) throws
            IOException {

        HttpClient httpclient = new HttpClient();
        PostMethod method = new PostMethod(url);

        StringRequestEntity requestEntity = new StringRequestEntity(data,
                "application/x-www-form-urlencoded", "UTF-8");
        method.setRequestEntity(requestEntity);

        int code = httpclient.executeMethod(method);

        byte[] responseBody = null;

        if (code == HttpStatus.SC_OK) {
            Header contentEncoding = method
                    .getResponseHeader("Content-Encoding");
            if (contentEncoding != null
                    && contentEncoding.getValue().toLowerCase().indexOf("gzip") > -1) {
                InputStream is = method.getResponseBodyAsStream();
                GZIPInputStream gzip = new GZIPInputStream(is);
                byte[] buf = new byte[1024];

                int num = -1;
                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                while ((num = gzip.read(buf, 0, buf.length)) != -1) {
                    baos.write(buf, 0, num);
                }
                responseBody = baos.toByteArray();
                baos.flush();
                baos.close();
                gzip.close();
                is.close();
            } else {
                responseBody = method.getResponseBody();
            }

            Header contentType = method.getResponseHeader("Content-Type");
            if (contentType != null) {
                String encoding = contentType.getValue().toUpperCase();

                Pattern pattern = Pattern.compile("CHARSET=([^;]*)");
                Matcher matcher = pattern.matcher(encoding);
                String charset = matcher.find() ? matcher.group(1) : null;

                if (charset != null) {
                    responseBody = (new String(responseBody, charset))
                            .getBytes("UTF-8");
                }
            }
        }
        String result = new String(responseBody);
        return result;
    }

    public static String concatParams(Map<String, String> params)
            throws UnsupportedEncodingException {
        Object[] key_arr = params.keySet().toArray();
        Arrays.sort(key_arr);
        String str = "";

        for (Object key : key_arr) {
            String val = params.get(key);
            key = URLEncoder.encode(key.toString(), "UTF-8");
            val = URLEncoder.encode(val, "UTF-8");
            str += "&" + key + "=" + val;
        }

        return str.replaceFirst("&", "");
    }

}
